package com.tanhua.server.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.RandomUtil;
import com.alibaba.fastjson.JSON;
import com.tanhua.autoconfig.template.HuanXinTemplate;
import com.tanhua.commons.utils.Constants;
import com.tanhua.dubbo.api.*;
import com.tanhua.model.domain.Question;
import com.tanhua.model.domain.UserInfo;
import com.tanhua.model.dto.RecommendUserDto;
import com.tanhua.model.mongo.RecommendUser;
import com.tanhua.model.mongo.Visitors;
import com.tanhua.model.vo.ErrorResult;
import com.tanhua.model.vo.NearUserVo;
import com.tanhua.model.vo.PageResult;
import com.tanhua.model.vo.TodayBest;
import com.tanhua.server.exception.BusinessException;
import com.tanhua.server.interceptor.UserHolder;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;


import java.text.SimpleDateFormat;
import java.util.*;

@Service
public class TanhuaService {

    @DubboReference
    private RecommendUserApi recommendUserApi;

    @DubboReference
    private UserInfoApi userInfoApi;
    @DubboReference
    private QuestionApi questionApi;
    @DubboReference
    private UserLikeApi userLikeApi;
    @Value("${tanhua.default.recommend.users}")
    private String recommendUser;
    @DubboReference
    private UserLocationApi userLocationApi;

    @DubboReference
    private VisitorsApi visitorsApi;
    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private HuanXinTemplate template;
    private MessagesService messagesService;

    private TanhuaService tanhuaService;

    //查询今日佳人数据
    public TodayBest todayBest() {
        //1、获取用户id
        Long userId = UserHolder.getUserId();
        //2、调用API查询得分最高的佳人
        RecommendUser recommendUser = recommendUserApi.queryWithMaxScore(userId);
        if (recommendUser == null) {
            recommendUser = new RecommendUser();
            recommendUser.setUserId(1l);
            recommendUser.setScore(99d);
        }
        //3、将RecommendUser转化为TodayBest对象
        UserInfo userInfo = userInfoApi.findById(recommendUser.getUserId());
        //3.1使用工具类将UserInfo对象转为TodayBest对象
        TodayBest vo = TodayBest.init(userInfo, recommendUser);
        //4、返回
        return vo;
    }
    /*查看佳人详情*/
    public TodayBest personalInfo(Long userId) {
        //1、根据用户id查询，用户详情
        UserInfo userInfo = userInfoApi.findById(userId);
        //2、根据操作人id和查看的用户id，查询两者的推荐数据
        RecommendUser user = recommendUserApi.queryByUserId(userId,UserHolder.getUserId());

        //构造访客数据，调用API保存
        Visitors visitors = new Visitors();
        visitors.setUserId(userId);
        visitors.setVisitorUserId(UserHolder.getUserId());
        visitors.setFrom("首页");
        visitors.setDate(System.currentTimeMillis());
        visitors.setVisitDate(new SimpleDateFormat("yyyyMMdd").format(new Date()));
        visitors.setScore(user.getScore());
        visitorsApi.save(visitors);

        //3、构造返回值
        return TodayBest.init(userInfo,user);
    }

    //查询分页退推荐好友列表
    public PageResult recommendation(RecommendUserDto dto) {
      /*
      *方式一:
      *
      //1.查询当前用户的id
        Long userId = UserHolder.getUserId();
        //2.根据id进行分页查询
       PageResult pr= recommendUserApi.queryRecommendUserList(dto.getPage(),dto.getPageSize(),userId);
        //3.获取分页查询表中的recommendUser的数据列表
        List<RecommendUser> items = (List<RecommendUser>) pr.getItems();
        //4.对集合进行非空判断
        if (items.size()==0||items==null){
            return pr;
        }
        // 5.遍历数据列表中的数据,根据每个recommendUser的id获取对应的信息 ,构造返回值
        //5、提取所有推荐的用户id列表,是否可以使用stream流
        List<TodayBest> list = new ArrayList<>();
        for (RecommendUser item : items) {
            Long recommendUserId = item.getUserId();
            //5.1根据用户id获取符合条件的用户对应的信息
            UserInfo userInfo = userInfoApi.findById(recommendUserId);
            //因为只展示某些信息,所以按要求获取对应信息,封装为vo对象
            if (userInfo!=null){
                    //进行条件筛选,
                //条件一:性别不能一致
                if (StringUtils.isNotEmpty(dto.getGender())&&!dto.getGender().equals(userInfo.getGender())){
                    continue;
                }
                //条件二:年龄不能大于该用户
                if (dto.getAge()!=null&&dto.getAge()<userInfo.getAge()){
                    continue;
                }
                TodayBest vo = TodayBest.init(userInfo, item);
                //筛选的好友不可能只有一个,所以使用集合存储
                list.add(vo);
            }
        }
        pr.setItems(list);
        return pr;   */
        /*
         * 方式二:优化代码
         * */

        //查询分页推荐好友列表
        //查询分页推荐好友列表
        //1、获取用户id
        Long userId = UserHolder.getUserId();
        //2、调用recommendUserApi分页查询数据列表（PageResult -- RecommendUser）
        PageResult pr = recommendUserApi.queryRecommendUserList(dto.getPage(), dto.getPagesize(), userId);
        //3、获取分页中的RecommendUser数据列表
        List<RecommendUser> items = (List<RecommendUser>) pr.getItems();
        //4、判断列表是否为空
        if (items == null || items.size() <= 0) {
            return pr;
        }
        //5、提取所有推荐的用户id列表
        List<Long> ids = CollUtil.getFieldValues(items, "userId", Long.class);
        UserInfo userInfo = new UserInfo();
        userInfo.setAge(dto.getAge());
        userInfo.setGender(dto.getGender());
        //6、构建查询条件，批量查询所有的用户详情
        Map<Long, UserInfo> map = userInfoApi.findByIds(ids, userInfo);
        //7、循环推荐的数据列表，构建vo对象
        List<TodayBest> list = new ArrayList<>();
        for (RecommendUser item : items) {

            UserInfo info = map.get(item.getUserId());
            if (info != null) {
                TodayBest vo = TodayBest.init(info, item);
                list.add(vo);
            }
        }
        //8、构造返回值
        pr.setItems(list);
        return pr;
    }


    //查看陌生人问题
    public String strangerQuestions(Long userId) {

        Question question = questionApi.findByUserId(userId);

        return question == null ? "喜欢我吗" : question.getTxt();
    }

    //回复陌生人问题
    public void replyQuestions(Long userId, String reply) {
        //如何回复?消息由我先发送给 控制台,然后控制台发送给环信,格式为JSON,环信再发送给佳人(她)
        //1.获取我的id
        Long myId = UserHolder.getUserId();
        //2.构造消息体
        UserInfo userInfo = userInfoApi.findById(myId);
        Map map = new HashMap();
        map.put("userId", myId);
        map.put("huanXinId", Constants.HX_USER_PREFIX + myId);
        map.put("nickname", userInfo.getNickname());
        map.put("strangerQuestion", strangerQuestions(userId));//回复陌生人的答案
        map.put("reply", reply);
        //3.转化为JSOn格式
        String message = JSON.toJSONString(map);
        //4.   调用template对象，发送消息
        Boolean aBoolean = template.sendMsg(Constants.HX_USER_PREFIX + userId, message);//1、接受方的环信id，2、消息
        //如果没有发送成功,抛出异常
        if (!aBoolean) {
            throw new BusinessException(ErrorResult.error());
        }
    }



    /*探花:推荐列表*/
    public List<TodayBest> queryCardsList() {
        //1、调用推荐API查询数据列表（排除喜欢/不喜欢的用户，数量限制）
        List<RecommendUser> users = recommendUserApi.queryCardsList(UserHolder.getUserId(), 10);
        //2.判断数据是否存在,如果不存在,构造默认数据
        if (CollUtil.isEmpty(users)) {
            //构造默认数据
            users = new ArrayList<>();
            String[] userIds = recommendUser.split(",");
            for (String userId : userIds) {
                RecommendUser recommendUser = new RecommendUser();
                recommendUser.setUserId(Convert.toLong(userId));
                recommendUser.setToUserId(UserHolder.getUserId());
                recommendUser.setScore(RandomUtil.randomDouble(60, 90));
                users.add(recommendUser);
            }
        }
        //3.构造Vo(TodayBest类型)
        List<Long> ids = CollUtil.getFieldValues(users, "userId", Long.class);
        Map<Long, UserInfo> map = userInfoApi.findByIds(ids, null);
        List<TodayBest> vos = new ArrayList<>();
        for (RecommendUser user : users) {
            UserInfo userInfo = map.get(user.getUserId());
            TodayBest todayBest = TodayBest.init(userInfo, user);
            vos.add(todayBest);
        }
        return vos;

    }

    /*探花:喜欢*/
    public void likeUser(Long likeUserId) {
        //1、调用API，保存喜欢数据(保存到MongoDB中)
        Boolean save = userLikeApi.saveOrUpdate(UserHolder.getUserId(), likeUserId, true);
        if (!save){
            //如果保存失败抛出异常
            throw new BusinessException(ErrorResult.error());
        }
        //2、操作redis，写入喜欢的数据，删除不喜欢的数据 (喜欢的集合，不喜欢的集合)
        redisTemplate.opsForSet().remove(Constants.USER_NOT_LIKE_KEY+UserHolder.getUserId(),likeUserId.toString());
        redisTemplate.opsForSet().add(Constants.USER_LIKE_KEY+UserHolder.getUserId(),likeUserId.toString());
        //3、判断是否双向喜欢
        if(isLike(likeUserId,UserHolder.getUserId())) {
            //4、添加好友
            messagesService.contacts(likeUserId);
        }
    }

    public Boolean isLike(Long userId,Long likeUserId) {
        String key = Constants.USER_LIKE_KEY+userId;
        return redisTemplate.opsForSet().isMember(key,likeUserId.toString());
    }




    /*探花:不喜欢*/
    public void notLikeUser(Long likeUserId) {
        //1、调用API，保存喜欢数据(保存到MongoDB中)
        Boolean save = userLikeApi.saveOrUpdate(UserHolder.getUserId(), likeUserId, false);
        if (!save){
            //如果保存失败抛出异常
            throw new BusinessException(ErrorResult.error());
        }
        //2、操作redis，写入喜欢的数据，删除不喜欢的数据 (喜欢的集合，不喜欢的集合)
        redisTemplate.opsForSet().add(Constants.USER_NOT_LIKE_KEY+UserHolder.getUserId(),likeUserId.toString());
        redisTemplate.opsForSet().remove(Constants.USER_LIKE_KEY+UserHolder.getUserId(),likeUserId.toString());
         //3、判断是否双向喜欢，删除好友(各位自行实现)
//        if(isLike(likeUserId,UserHolder.getUserId())) {
//            //删除Redis中的数据
//
//        }
    }

    /*搜附近
    * */
    public List<NearUserVo> queryNearUser(String gender, String distance) {
        //1.调用方法搜索附近,返回所有的id
        List<Long> userIds=userLocationApi.queryNearUser(UserHolder.getUserId(),distance);
        if (CollUtil.isEmpty(userIds)){
            return new ArrayList<>();    //2.如果为空,返回
        }
        //3.如果不为空,根据id和查询条件查询对应的用户集合
        UserInfo userInfo = new UserInfo();
        userInfo.setGender(gender);
        Map<Long, UserInfo> map = userInfoApi.findByIds(userIds, userInfo);
        //4,构造返回值
        List<NearUserVo> vos = new ArrayList<>();
        for (Long userId : userIds) {
            //首先要排除自身
            if (userId==UserHolder.getUserId()){
                continue;
            }
            UserInfo info = map.get(userId);
            if (info!=null){
                NearUserVo vo = NearUserVo.init(info);
                vos.add(vo);
            }
        }
        return vos;
    }
}